package net.yxsoft.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.jfinal.kit.PathKit;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Page;
import com.jfinal.plugin.activerecord.Record;
import net.yxsoft.bean.deployApp.DeployRequest;
import net.yxsoft.kit.Helper;
import net.yxsoft.kit.RemoteCommandKit;
import net.yxsoft.model.formdesigner.FnFormData;
import net.yxsoft.service.common.BaseService;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml;
import rapid.core.Authuser;
import rapid.core.TResult;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

public class RemoteAppService extends BaseService {
    public static final RemoteAppService INSTANCE = new RemoteAppService();

    /**
     * 分页查询表单数据
     * code 表单code值
     *  map 数据查询条件（包含pageNum，pageSize）
     * */
    public Page<Record> selectBlockDataList(String code,Map<String,Object> map){
        int pageNumber = map.get("pageNum")==null?1: (int) map.get("pageNum"); // 默认为第一页
        if(pageNumber<=0){
            pageNumber=1;
        }
        int pageSize = map.get("pageSize")==null?1: (int) map.get("pageSize"); // 默认每页显示10条数据
        if(pageSize<=0){
            pageSize=1;
        }
        //设置动态表单为共享数据查询和搜索
        String where="where attrib_01=(SELECT id FROM fn_form WHERE code='"+code+"')";
        List<Object> params = new ArrayList<Object>();
            for (String key:map.keySet()) {
                if (map.get(key)!=null && StringUtils.isNotBlank(map.get(key).toString()) && !"pageNum".equals(key) && !"pageSize".equals(key)) {
                    where += " and "+key+" like ?";
                    params.add("%" + map.get(key) + "%");
                }
            }
        //分页
        Page<Record> record = Db.paginate(pageNumber, pageSize, "select *", " from fn_form_data " + where +" order by created desc", params.toArray());
        return record;
    }

    /**
     * 新页面--部署应用--部署功能
     *  cid 数据cid
     * */
    public TResult deployApp(DeployRequest deploy,Authuser user){
        //应用服务单元管理
        Record yyfwForm = Db.findFirst("SELECT id FROM fn_form WHERE code='yyfwdygl'");
        String parRowId=null;
        if(yyfwForm!=null){
            // attrib_37 --所属站点
            FnFormData fnFormDataFind = FnFormData.dao.findFirst("select * from fn_form_data where attrib_01=? and attrib_37= ? ", yyfwForm.getStr("id"), deploy.getSiteName());
            if(fnFormDataFind!=null){
                return  TResult.fail("msg", "已存在相同名称站点！");
            }
            FnFormData fnFormData =new FnFormData();
            //记录登入用户信息
            if(user!=null){
                fnFormData.setCreatedBy(user.getId());
                fnFormData.setCreatedByName(user.getName());
                fnFormData.setLastUpdBy(user.getId());
                fnFormData.setLastUpdByName(user.getName());
            }
            String uuid = Helper.bulidUUID();
            parRowId=uuid;//存储关联表Id,后期删除可以通过row_id一次性删除相关数据
            fnFormData.setConflictId(uuid);//设置主键
            fnFormData.setRowId(uuid);//设置rowId
            fnFormData.setAttrib01(yyfwForm.getStr("id"));
            fnFormData.setAttrib37(deploy.getSiteName());//所属站点
            fnFormData.setAttrib06(deploy.getContact());//联系方式
            fnFormData.save();//保存
        }

        //主机信息管理
        Record zjxxForm = Db.findFirst("SELECT id FROM fn_form WHERE code='zjxxgl'");
        if(zjxxForm!=null){
            FnFormData fnFormData =new FnFormData();
            //记录登入用户信息
            if(user!=null){
                fnFormData.setCreatedBy(user.getId());
                fnFormData.setCreatedByName(user.getName());
                fnFormData.setLastUpdBy(user.getId());
                fnFormData.setLastUpdByName(user.getName());
            }
            String uuid = Helper.bulidUUID();
            fnFormData.setConflictId(uuid);//设置主键
            fnFormData.setRowId(parRowId);//设置rowId --使用parPowId方便后期删除相关数据
            fnFormData.setAttrib01(zjxxForm.getStr("id"));
            fnFormData.setAttrib03(deploy.getHostIp());//主机IP
            fnFormData.setAttrib04(deploy.getHostPort());//主机端口
            fnFormData.setAttrib05(deploy.getHostUser());//主机用户
            fnFormData.setAttrib06(deploy.getHostPassword());//主机密码
            fnFormData.setAttrib07(deploy.getDbUserName());//数据库用户名
            fnFormData.setAttrib08(deploy.getDbPassword());//数据库密码
            fnFormData.setAttrib09(deploy.getDbPort());//数据库端口
            fnFormData.setAttrib31(deploy.getSiteName());//站点名称
            fnFormData.setAttrib10(deploy.getAppPort());//应用服务端口
            fnFormData.save();//保存
        }


      return TResult.success("msg","站点："+deploy.getSiteName()+",部署成功！");
    }

    //上传tpServer服务到指定服务器
    public void deployDataBase(DeployRequest deploy) throws Exception {
        //部署服务器路径
        String targetPath="/opt";
        long timeMillis = System.currentTimeMillis();
        String filesPath;
        String databasePath;
        String folderName;
        if("原生部署".equals(deploy.getDeployWay())){
            folderName="mysql-ori";
            databasePath= PathKit.getRootClassPath() + "/mysql-ori";
            filesPath=PathKit.getWebRootPath() +"/files/mysql-ori-"+timeMillis;
        }else{
            folderName="mysql-vm";
            databasePath= PathKit.getRootClassPath() + "/mysql-vm";
            filesPath=PathKit.getWebRootPath() +"/files/mysql-vm-"+timeMillis;
        }

        //创建父文件夹
        File pathFile = new File(filesPath);
        //添加--mode=go+rx 给里面的文件加上执行权限
        Runtime.getRuntime().exec("tar -czvf "+filesPath+".tar.gz  --mode=go+rx -C "+databasePath +" .");
        //上传到远程服务器上
        RemoteCommandKit.remoteFileUploader(deploy.getHostIp(),deploy.getHostPort(),deploy.getHostUser(),deploy.getHostPassword(),pathFile.getName()+".tar.gz",filesPath+".tar.gz",targetPath);
        //解压文件夹
        String[] tarCommands = { "cd "+targetPath+" && mkdir -p "+folderName+" && tar -xzvf "+pathFile.getName()+".tar.gz -C "+folderName };
        //使用execRemoteCommandByResponse才能执行成功
        RemoteCommandKit.execRemoteCommandByResponse(deploy.getHostIp(),deploy.getHostPort(),deploy.getHostUser(),deploy.getHostPassword(),tarCommands);

        //启动文件
        String[] startdb = { "cd "+targetPath+"/"+folderName+" && ./startdb.sh "+deploy.getDbUserName()+" "+deploy.getDbPassword()+" "+deploy.getDbPort() };
        //使用execRemoteCommandByResponse才能执行成功
        RemoteCommandKit.execRemoteCommandByResponse(deploy.getHostIp(),deploy.getHostPort(),deploy.getHostUser(),deploy.getHostPassword(),startdb);
        //删除已经部署完的临时压缩包
        File deleFile = new File(filesPath+".tar.gz");
        deleFile.delete();
    }

    //上传tpServer服务到指定服务器
    public void deployTpServer(DeployRequest deploy) throws Exception {
        long timeMillis = System.currentTimeMillis();
        String filesPath=PathKit.getWebRootPath() +"/files/tpServer-"+timeMillis;
        //创建父文件夹
        File pathFile = new File(filesPath);
        //判断⽂件夹是否存在
        if (!pathFile.exists()) {
            //如果⽂件夹不存在，则创建新的的⽂件夹
            pathFile.mkdirs();
        }
        //拷贝tpserver项目到指定文件夹下
        File srcDir = new File("/opt/tp-server");
        FileUtils.copyDirectory(srcDir, pathFile);
        // 读取现有的YAML文件内容
        Yaml yaml = new Yaml();
        Map<String, Object> devData = yaml.load(new FileInputStream(filesPath+"/config/config/application-dev.yml"));
        //端口修改
        Map<String, Object> server = (Map<String, Object>) devData.get("server");
        server.put("port",Integer.parseInt(deploy.getAppPort()));
        //数据库修改
        Map<String, Object> spring = (Map<String, Object>) devData.get("spring");
        Map<String, Object> datasource = (Map<String, Object>) spring.get("datasource");
        datasource.put("url","jdbc:mysql://"+deploy.getHostIp()+":"+deploy.getDbPort()+"/xwtp?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC");
        datasource.put("username",deploy.getDbUserName());
        datasource.put("password",deploy.getDbPassword());
        //区块地址
        Map<String, Object> blockChain = (Map<String, Object>) devData.get("blockChain");
        Map<String, Object> contractname = (Map<String, Object>) blockChain.get("contractname");
        contractname.put("evidencename",deploy.getEvidence());
        contractname.put("ordername",deploy.getShare());
        contractname.put("statename",deploy.getShare());
        // 设置DumperOptions以保留注释和层级结构
        DumperOptions options = new DumperOptions();
        options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); // 保留层级结构
        options.setPrettyFlow(true); // 保留注释和布局
        options.setAllowReadOnlyProperties(true); // 保留注释
        // 创建一个新的YAML文件，并将修改后的内容写入其中，保留注释和层级结构
        FileWriter writer = new FileWriter(filesPath+"/config/config/application-dev.yml");
        Yaml yamlWithCommentsAndHierarchy = new Yaml(options);
        yamlWithCommentsAndHierarchy.dump(devData, writer);
        writer.close();

        // 读取现有的YAML文件内容
        Yaml proYaml = new Yaml();
        Map<String, Object> proData = proYaml.load(new FileInputStream(filesPath+"/config/config/application-pro.yml"));
        //端口修改
        Map<String, Object> proServer = (Map<String, Object>) proData.get("server");
        proServer.put("port",Integer.parseInt(deploy.getAppPort()));
        //数据库修改
        Map<String, Object> proSpring = (Map<String, Object>) proData.get("spring");
        Map<String, Object> proDatasource = (Map<String, Object>) proSpring.get("datasource");
        proDatasource.put("url","jdbc:mysql://"+deploy.getHostIp()+":"+deploy.getDbPort()+"/xwtp?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC");
        proDatasource.put("username",deploy.getDbUserName());
        proDatasource.put("password",deploy.getDbPassword());
        //区块地址
        Map<String, Object> proBlockChain = (Map<String, Object>) proData.get("blockChain");
        Map<String, Object> proContractname = (Map<String, Object>) proBlockChain.get("contractname");
        proContractname.put("evidencename",deploy.getEvidence());
        proContractname.put("ordername",deploy.getShare());
        proContractname.put("statename",deploy.getShare());
        // 设置DumperOptions以保留注释和层级结构
        DumperOptions proOptions = new DumperOptions();
        proOptions.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); // 保留层级结构
        proOptions.setPrettyFlow(true); // 保留注释和布局
        proOptions.setAllowReadOnlyProperties(true); // 保留注释
        // 创建一个新的YAML文件，并将修改后的内容写入其中，保留注释和层级结构
        FileWriter proWriter = new FileWriter(filesPath+"/config/config/application-pro.yml");
        Yaml proOptionsyamlWithCommentsAndHierarchy = new Yaml(proOptions);
        proOptionsyamlWithCommentsAndHierarchy.dump(proData, proWriter);
        proWriter.close();

        //项目目录名
        String tpServerName="tp-server";
        //部署服务器路径
        String targetPath="/home";
        //压缩文件夹
        //添加--mode=go+rx 给里面的文件加上执行权限
        Runtime.getRuntime().exec("tar -czvf "+filesPath+".tar.gz  --mode=go+rx -C "+filesPath +" .");
        //上传到远程服务器上
        RemoteCommandKit.remoteFileUploader(deploy.getHostIp(),deploy.getHostPort(),deploy.getHostUser(),deploy.getHostPassword(),pathFile.getName()+".tar.gz",filesPath+".tar.gz",targetPath);
        //解压文件夹
        String[] tarCommands = { "cd "+targetPath+" && mkdir -p "+tpServerName+" && tar -xzvf "+pathFile.getName()+".tar.gz -C "+tpServerName };
        //使用execRemoteCommandByResponse才能执行成功
        RemoteCommandKit.execRemoteCommandByResponse(deploy.getHostIp(),deploy.getHostPort(),deploy.getHostUser(),deploy.getHostPassword(),tarCommands);
        //启动tp-server服务
        String[] startCommand = { "cd "+targetPath+"/"+tpServerName+" && ./start.sh restart" };
        //使用execRemoteCommandByResponse才能执行成功
        RemoteCommandKit.execRemoteCommandByResponse(deploy.getHostIp(),deploy.getHostPort(),deploy.getHostUser(),deploy.getHostPassword(),startCommand);
        //删除已经部署完的临时压缩包
        File deleFile = new File(filesPath+".tar.gz");
        deleFile.delete();
        //保证每次都是最新的
        FileUtils.deleteDirectory(pathFile);//删除部署目录文件
    }

    /**
     * 新页面--应用服务单元管理--查看应用单元状态
     *  cid 数据cid
     * */
    public  Map selectUnitStatusByCid(String cid){
        Map stautsMap = new HashMap<>();
            stautsMap.put("appStatus",null);//应用状态
            stautsMap.put("dataStatus",null);//数据任务状态
            stautsMap.put("fileStatus",null);//文件应用状态
        try{
            Record record = Db.findFirst("select * from fn_form_data where conflict_id= ?",cid);
            String appIp = record.getStr("attrib_07");//服务器IP地址
            String appPort = record.getStr("attrib_08");//应用端口号
            String appAccount = record.getStr("attrib_31");//应用账号
            String appPassword = record.getStr("attrib_32");//应用密码

            //查看项目是否启动
            String[] StautsCommands = { "ps -ef | grep tp-server.jar | grep -v grep"};
            String stauts = RemoteCommandKit.execRemoteCommandByReturn(appIp, appPort, appAccount, appPassword, StautsCommands);
            if(StringUtils.isBlank(stauts)){
                stautsMap.put("appStatus",false);
            }else{
                stautsMap.put("appStatus",true);
            }
            //登入接口
            String loginUrl="http://"+appIp+":5488/api/manage/user/login";
            String loginParam="{ \"name\":\"admin\", \"pwd\":\"pwd123\" }";
            //调用登入接口获得登入认证token
            JsonNode jsonNode = mocExecPost(loginUrl, loginParam, null);
            String token = jsonNode.get("data").get("token").asText();

            //数据任务状态地址
            String dataTaskUrl="http://"+appIp+":5488/api/manage/task/getDataTaskState";
            JsonNode dataNode = mocExecGet(dataTaskUrl, token);
            if("0".equals(dataNode.get("code").asText())){
                stautsMap.put("dataStatus",dataNode.get("data").asText());
            }else{
                stautsMap.put("dataStatus",false);
            }

            //数据任务状态地址
            String fileTaskUrl="http://"+appIp+":5488/api/manage/task/getFileTaskState";
            JsonNode fileNode = mocExecGet(fileTaskUrl, token);
            if("0".equals(fileNode.get("code").asText())){
                stautsMap.put("fileStatus",fileNode.get("data").asText());
            }else{
                stautsMap.put("fileStatus",false);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return  stautsMap;
    }


    /**
     *  切换应用服务单元启停状态--新页面
     *  cid 数据cid
     * */
    public  Map switchAppStatusByCid(String cid,boolean status){
        Map returnMap = new HashMap<>();
        try{
            Record record = Db.findFirst("select * from fn_form_data where conflict_id= ?",cid);
            String appIp = record.getStr("attrib_07");//服务器IP地址
            String appPort = record.getStr("attrib_08");//应用端口号
            String appAccount = record.getStr("attrib_31");//应用账号
            String appPassword = record.getStr("attrib_32");//应用密码
            String appPath =record.getStr("ATTRIB_09");//应用所在路径
            String startCommand =record.getStr("ATTRIB_12");//应用启动命令
            String killCommand = record.getStr("ATTRIB_13");//应用停止命令
            //是否启动ture,启动停止不成功看文件权限
            if(status){
                //先停止进程
                String[] execKill = {killCommand};
                RemoteCommandKit.execRemoteCommand(appIp, appPort, appAccount, appPassword,execKill);

                String execPath = "cd "+appPath;
                String[] exec = {execPath,startCommand};
                RemoteCommandKit.execRemoteCommand(appIp, appPort, appAccount, appPassword,exec);
            }else{
                //先停止进程
                String[] execKill = {killCommand};
                RemoteCommandKit.execRemoteCommand(appIp, appPort, appAccount, appPassword,execKill);
            }
            returnMap.put("msg","执行成功！");

        }catch (Exception e){
            e.printStackTrace();
            returnMap.put("msg",e.toString());
        }
        return  returnMap;
    }

    /**
     * 切换数据任务状态启停--新页面
     *  cid 数据cid
     * */
    public  JsonNode switchDataStatusByCid(String cid,boolean status){
        try{
            Record record = Db.findFirst("select * from fn_form_data where conflict_id= ?",cid);
            String appIp = record.getStr("attrib_07");//服务器IP地址
            //登入接口
            String loginUrl="http://"+appIp+":5488/api/manage/user/login";
            String loginParam="{ \"name\":\"admin\", \"pwd\":\"pwd123\" }";
            //调用登入接口获得登入认证token
            JsonNode jsonNode = mocExecPost(loginUrl, loginParam, null);
            String token = jsonNode.get("data").get("token").asText();
            //数据任务状态地址
            String dataTaskUrl="http://"+appIp+":5488/api/manage/task/setDataTaskState";
            //是否启动ture,启动停止不成功看文件权限
            if(status){
                JSONObject jsonParam = new JSONObject();
                jsonParam.put("state",status);
                JsonNode dataNode = mocExecPost(dataTaskUrl,jsonParam.toString(), token);
                return dataNode;
            }else{
                JSONObject jsonParam = new JSONObject();
                jsonParam.put("state",status);
                JsonNode dataNode = mocExecPost(dataTaskUrl,jsonParam.toString(), token);
                return dataNode;
            }
        }catch (Exception e){
            e.printStackTrace();
            ObjectMapper objectMapper = new ObjectMapper(); // 创建一个ObjectMapper对象，用于处理JSON
            ObjectNode res = objectMapper.createObjectNode(); // 创建一个ObjectNode对象
            // 添加msg字段到ObjectNode对象中
            res.put("error", e.toString());
            return res;
        }
    }


    /**
     * 切换文件任务状态启停--新页面
     *  cid 数据cid
     * */
    public  JsonNode switchFileStatusByCid(String cid,boolean status){
        try{
            Record record = Db.findFirst("select * from fn_form_data where conflict_id= ?",cid);
            String appIp = record.getStr("attrib_07");//服务器IP地址
            //登入接口
            String loginUrl="http://"+appIp+":5488/api/manage/user/login";
            String loginParam="{ \"name\":\"admin\", \"pwd\":\"pwd123\" }";
            //调用登入接口获得登入认证token
            JsonNode jsonNode = mocExecPost(loginUrl, loginParam, null);
            String token = jsonNode.get("data").get("token").asText();
            //文件任务状态更改地址
            String fileTaskUrl="http://"+appIp+":5488/api/manage/task/setFielTaskState";
            //是否启动ture,启动停止不成功看文件权限
            if(status){
                JSONObject jsonParam = new JSONObject();
                jsonParam.put("state",status);
                JsonNode dataNode = mocExecPost(fileTaskUrl,jsonParam.toString(), token);
                return dataNode;
            }else{
                JSONObject jsonParam = new JSONObject();
                jsonParam.put("state",status);
                JsonNode dataNode = mocExecPost(fileTaskUrl,jsonParam.toString(), token);
                return dataNode;
            }
        }catch (Exception e){
            e.printStackTrace();
            ObjectMapper objectMapper = new ObjectMapper(); // 创建一个ObjectMapper对象，用于处理JSON
            ObjectNode res = objectMapper.createObjectNode(); // 创建一个ObjectNode对象
            // 添加msg字段到ObjectNode对象中
            res.put("error", e.toString());
            return res;
        }
    }




    /**
     * 应用服务单元管理--新增数据方法
     * user 登入用户
     *  map 数据
     * */
    public  TResult InsertFormData(Authuser user, Map<String,Object> map){
        try{
            FnFormData fnFormData = new FnFormData();
            for (String key:map.keySet()) {
                if("code".equals(key)){
                    continue;
                }
                //循环插入字段属性
                fnFormData.set(key,map.get(key));
            }
            Record fnForm = Db.findFirst("SELECT id FROM fn_form WHERE code=?",map.get("code"));
            fnFormData.set("attrib_01",fnForm.getStr("id"));//设置动态表单ID--应用服务单元管理
            String uuid = Helper.bulidUUID();
            fnFormData.setConflictId(uuid);//设置主键
            fnFormData.setRowId(uuid);//设置rowId
            //记录登入用户信息
            if(user!=null){
                fnFormData.setCreatedBy(user.getId());
                fnFormData.setCreatedByName(user.getName());
                fnFormData.setLastUpdBy(user.getId());
                fnFormData.setLastUpdByName(user.getName());
            }
            fnFormData.save();
            return  TResult.success().set("msg", "新增成功！");
        }catch (Exception e){
            e.printStackTrace();
            return  TResult.fail().set("msg", "新增失败！");
        }
    }


    /**
     * 应用服务单元管理--新增数据方法
     * user 登入用户
     *  map 数据
     * */
    public  TResult insertUnit(Authuser user, Map<String,Object> map){
        try{
            FnFormData fnFormData = new FnFormData();
            for (String key:map.keySet()) {
                //循环插入字段属性
                fnFormData.set(key,map.get(key));
            }
            Record fnForm = Db.findFirst("SELECT id FROM fn_form WHERE code='yyfwdygl'");
            fnFormData.set("attrib_01",fnForm.getStr("id"));//设置动态表单ID--应用服务单元管理
            String uuid = Helper.bulidUUID();
            fnFormData.setConflictId(uuid);//设置主键
            fnFormData.setRowId(uuid);//设置rowId
            //记录登入用户信息
            if(user!=null){
                fnFormData.setCreatedBy(user.getId());
                fnFormData.setCreatedByName(user.getName());
                fnFormData.setLastUpdBy(user.getId());
                fnFormData.setLastUpdByName(user.getName());
            }
            fnFormData.save();
            return  TResult.success().set("msg", "新增成功！");
        }catch (Exception e){
            e.printStackTrace();
            return  TResult.fail().set("msg", "新增失败！");
        }
    }

    /**
     * 服务与配置变更管理--新增数据方法
     * user 登入用户
     *  map 数据
     * */
    public  TResult insertServiceConfig(Authuser user, Map<String,Object> map){
        try{
            FnFormData fnFormData = new FnFormData();
            for (String key:map.keySet()) {
                //循环插入字段属性
                fnFormData.set(key,map.get(key));
            }
            Record fnForm = Db.findFirst("SELECT id FROM fn_form WHERE code='fwpzbggl'");
            fnFormData.set("attrib_01",fnForm.getStr("id"));//设置动态表单ID--服务与配置变更管理
            String uuid = Helper.bulidUUID();
            fnFormData.setConflictId(uuid);//设置主键
            fnFormData.setRowId(uuid);//设置rowId
            //记录登入用户信息
            if(user!=null){
                fnFormData.setCreatedBy(user.getId());
                fnFormData.setCreatedByName(user.getName());
                fnFormData.setLastUpdBy(user.getId());
                fnFormData.setLastUpdByName(user.getName());
            }
            fnFormData.save();
            return  TResult.success().set("msg", "新增成功！");
        }catch (Exception e){
            e.printStackTrace();
            return  TResult.fail().set("msg", "新增失败！");
        }
    }

    /**
     * 应用服务单元管理--修改数据方法
     * user 登入用户
     *  map 数据
     * */
    public  TResult updatePublicMethods(Authuser user, Map<String,Object> map){
        try{
            FnFormData fnFormData = FnFormData.dao.findById(map.get("conflict_id"));
            if(fnFormData==null){
                return  TResult.fail().set("msg", "修改失败！");
            }
            for (String key:map.keySet()) {
                //循环插入字段属性
                fnFormData.set(key,map.get(key));
            }
            //记录登入用户修改信息
            if(user!=null){
                fnFormData.setLastUpdBy(user.getId());
                fnFormData.setLastUpdByName(user.getName());
            }
            fnFormData.update();
            return  TResult.success().set("msg", "修改成功！");
        }catch (Exception e){
            e.printStackTrace();
            return  TResult.fail().set("msg", "修改失败！");
        }
    }

    /**
     * 应用服务单元管理--删除数据方法
     *  cid 数据cid
     * */
    public  TResult deletePublicMethods(String cid){
        try{
            FnFormData fnFormData = new FnFormData();
            fnFormData.setConflictId(cid);
            fnFormData.delete();
            return  TResult.success().set("msg", "删除成功！");
        }catch (Exception e){
            e.printStackTrace();
            return  TResult.fail().set("msg", "删除失败！");
        }
    }

    /**
     * 查询单元站点区块各类数据信息
     * user 登入用户
     *  map 数据
     * */
    public  TResult selectUnitBlockData(String name){
        try{
            Map map = new HashMap<>();
            map.put("OrderID",null);
            map.put("StateID",null);
            map.put("EvdcHash",null);
            map.put("status",null);
            Record gx = Db.findFirst("SELECT ATTRIB_06 AS contractName FROM fn_form_data WHERE attrib_01=(SELECT id FROM fn_form WHERE code='znhy') and ATTRIB_12= ? and ATTRIB_35= ? ", name, "共享业务");
            Record cz = Db.findFirst("SELECT ATTRIB_06 AS contractName FROM fn_form_data WHERE attrib_01=(SELECT id FROM fn_form WHERE code='znhy') and ATTRIB_12= ? and ATTRIB_35= ? ", name, "存证业务");
            if(gx!=null){
                //共享数据查询和搜索表单获取指令数据,状态数据最新一条数据
                Record zl= Db.findFirst("SELECT ATTRIB_31 AS OrderID,last_upd AS Time FROM fn_form_data WHERE attrib_01=(SELECT id FROM fn_form WHERE code='yyfwslxx') and attrib_41= ? and attrib_54= ? order by last_upd desc ", gx.getStr("contractName"), "指令数据");
                Record zt = Db.findFirst("SELECT ATTRIB_31 AS StateID,last_upd AS Time FROM fn_form_data WHERE attrib_01=(SELECT id FROM fn_form WHERE code='yyfwslxx') and attrib_41= ? and attrib_54= ? order by last_upd desc ", gx.getStr("contractName"), "状态数据");
                if(zl!=null){
                    Map Order = new HashMap<>();
                    Order.put("OrderID",zl.getStr("OrderID"));
                    String time = getTimeDifference(zl.getStr("Time"));
                    Order.put("Time",time);
                    map.put("OrderID",Order);
                }
                if(zt!=null){
                    Map State = new HashMap<>();
                    State.put("StateID",zt.getStr("StateID"));
                    String time = getTimeDifference(zt.getStr("Time"));
                    State.put("Time",time);
                    map.put("StateID",State);
                }
            }
            if(cz!=null){
                //存证数据查询和搜索表单最新一条数据
                Record zl= Db.findFirst("SELECT ATTRIB_12 AS EvdcHash,last_upd AS Time FROM fn_form_data WHERE attrib_01=(SELECT id FROM fn_form WHERE code='czsjcxhss') and attrib_41= ?  order by last_upd desc ", cz.getStr("contractName"));
                if(zl!=null){
                    Map Evdc = new HashMap<>();
                    Evdc.put("EvdcHash",zl.getStr("EvdcHash"));
                    String time = getTimeDifference(zl.getStr("Time"));
                    Evdc.put("Time",time);
                    map.put("EvdcHash",Evdc);
                }
            }
            //应用服务单元管理表单状态
            Record record = Db.findFirst("SELECT attrib_10 AS status FROM fn_form_data WHERE attrib_01=(SELECT id FROM fn_form WHERE code='yyfwdygl') and attrib_03= ? ",name);
            if(record!=null){
                map.put("status",record.getStr("status"));
            }
            return  TResult.success().data(map);
        }catch (Exception e){
            e.printStackTrace();
            return  TResult.fail().set("msg", "获取失败！");
        }
    }


    /**
     * 返回时间间隔时长[天前,小时前,分钟前,秒前]
     * */
    public static String getTimeDifference(String timeString) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss[.S]");
        LocalDateTime time = LocalDateTime.parse(timeString, formatter); // 将时间字符串解析为LocalDateTime对象
        LocalDateTime now = LocalDateTime.now(); // 当前时间
        Duration duration = Duration.between(time, now);
        long seconds = Math.abs(duration.getSeconds());
        long minutes = Math.abs(duration.toMinutes());
        long hours = Math.abs(duration.toHours());
        long days = Math.abs(duration.toDays());
        if (days > 0) {
            return days + "天前";
        } else if (hours > 0) {
            return hours + "小时前";
        } else if (minutes > 0) {
            return minutes + "分钟前";
        } else {
            return seconds + "秒前";
        }
    }

    /**
     * 启动服务
     *  cid 表单数据cid
     * */
    public  TResult startRemoteApp(String cid){
        try{
            Record record = Db.findFirst("select * from fn_form_data where conflict_id= ?",cid);
            String host = record.getStr("ATTRIB_07");//应用IP地址
            String port = record.getStr("ATTRIB_08");//应用端口
            String username = record.getStr("ATTRIB_31");//应用账号
            String password = record.getStr("ATTRIB_32");//应用密码
            String appPath =record.getStr("ATTRIB_09");//应用所在路径
            String startCommand =record.getStr("ATTRIB_12");//应用启动命令
            String killCommand = record.getStr("ATTRIB_13");//应用停止命令
            String appStatus = record.getStr("ATTRIB_58");//应用状态监控命令
            //先停止进程
            String[] execKill = {killCommand};
            RemoteCommandKit.execRemoteCommand(host,port,username,password,execKill);
            //进入路径地址执行命令，启动服务
            String execPath = "cd "+appPath;
            String[] exec = {execPath,startCommand};
            RemoteCommandKit.execRemoteCommand(host,port,username,password,exec);
            //更新服务状态
            Db.update("update fn_form_data set ATTRIB_10=? where conflict_id= ? ","正常",cid);
            /*//查看服务状态，更新状态节点
            String[] execStatus = {appStatus};
            int i = RemoteCommandKit.execRemoteCommandByResponse(host, port, username, password, execStatus);
            if(i==0){
                //更新服务状态
                Db.update("update fn_form_data set ATTRIB_10=? where conflict_id= ? ","正常",cid);
            }else {
                //更新服务状态
                Db.update("update fn_form_data set ATTRIB_10=? where conflict_id= ? ","停止",cid);
                return TResult.success().set("msg", "出现异常！请排查参数！");
            }*/
        }catch (Exception e){
            e.printStackTrace();
            return TResult.success().set("msg", "出现异常！请排查参数！");
        }
        return  TResult.success().set("msg", "执行成功！");
    }

    /**
     * 停止服务
     *  cid 表单数据cid
     * */
    public TResult stopRemoteApp(String cid){
        try{
            Record record = Db.findFirst("select * from fn_form_data where conflict_id= ?",cid);
            String host = record.getStr("ATTRIB_07");//应用IP地址
            String port = record.getStr("ATTRIB_08");//应用端口
            String username = record.getStr("ATTRIB_31");//应用账号
            String password = record.getStr("ATTRIB_32");//应用密码
            String appPath =record.getStr("ATTRIB_09");//应用所在路径
            String startCommand =record.getStr("ATTRIB_12");//应用启动命令
            String killCommand = record.getStr("ATTRIB_13");//应用停止命令
            String appStatus = record.getStr("ATTRIB_58");//应用状态监控命令
            //停止进程
            String[] execKill = {killCommand};
            RemoteCommandKit.execRemoteCommand(host,port,username,password,execKill);
            //更新服务状态
            Db.update("update fn_form_data set ATTRIB_10=? where conflict_id= ? ","停止",cid);
        }catch (Exception e){
            e.printStackTrace();
            return TResult.success().set("msg", "出现异常！请排查参数！");
        }
        return  TResult.success().set("msg", "执行成功！");
    }

    /**
     * 部署服务脚本
     *  cid 表单数据cid
     * */
    public TResult uploadToRemote(String cid){
        try{
            Record record = Db.findFirst("select * from fn_form_data where conflict_id= ?",cid);
            String host = record.getStr("ATTRIB_07");//应用IP地址
            String port = record.getStr("ATTRIB_08");//应用端口
            String username = record.getStr("ATTRIB_31");//应用账号
            String password = record.getStr("ATTRIB_32");//应用密码
            String exeFile = record.getStr("ATTRIB_33");//执行文件
            String fileName = record.getStr("ATTRIB_34");//文件名
            String appPath =record.getStr("ATTRIB_09");//应用所在路径
            String parentPath = PathKit.getWebRootPath() + File.separator;//文件根路径
            RemoteCommandKit.remoteFileUploader(host,port,username,password,fileName,parentPath+exeFile,appPath);
        }catch (Exception e){
            e.printStackTrace();
            return TResult.success().set("msg", "出现异常！请排查参数！");
        }
        return  TResult.success().set("msg", "部署成功！");
    }

    /**
     * 更新服务
     *  cid 表单数据cid
     * */
    public TResult updateRemoteApp(String cid){
        try{
            Record record = Db.findFirst("select * from fn_form_data where conflict_id= ?",cid);
            String host = record.getStr("ATTRIB_07");//应用IP地址
            String port = record.getStr("ATTRIB_08");//应用端口
            String username = record.getStr("ATTRIB_31");//应用账号
            String password = record.getStr("ATTRIB_32");//应用密码
            String exeFile = record.getStr("ATTRIB_33");//执行文件
            String fileName = record.getStr("ATTRIB_34");//文件名
            String appPath =record.getStr("ATTRIB_09");//应用所在路径
            String startCommand =record.getStr("ATTRIB_12");//应用启动命令
            String killCommand = record.getStr("ATTRIB_13");//应用停止命令
            String appStatus = record.getStr("ATTRIB_58");//应用状态监控命令
            String parentPath = PathKit.getWebRootPath() + File.separator;//文件根路径

            //先停止进程
            String[] execKill = {killCommand};
            RemoteCommandKit.execRemoteCommand(host,port,username,password,execKill);
            //覆盖文件
            RemoteCommandKit.remoteFileUploader(host,port,username,password,fileName,parentPath+exeFile,appPath);
            //进入路径地址执行命令，启动服务
            String execPath = "cd "+appPath;
            String[] exec = {execPath,startCommand};
            RemoteCommandKit.execRemoteCommand(host,port,username,password,exec);
            //更新服务状态
            Db.update("update fn_form_data set ATTRIB_10=? where conflict_id= ? ","正常",cid);
           /* //查看服务状态，更新状态节点
            String[] execStatus = {appStatus};
            int i = RemoteCommandKit.execRemoteCommandByResponse(host, port, username, password, execStatus);
            if(i==0){
                //更新服务状态
                Db.update("update fn_form_data set ATTRIB_10=? where conflict_id= ? ","正常",cid);
            }else {
                //更新服务状态
                Db.update("update fn_form_data set ATTRIB_10=? where conflict_id= ? ","停止",cid);
                return TResult.success().set("msg", "出现异常！请排查参数！");
            }*/
        }catch (Exception e){
            e.printStackTrace();
            return TResult.success().set("msg", "出现异常！请排查参数！");
        }
        return  TResult.success().set("msg", "更新成功！");
    }

    /**
     * 服务与配置变更管理 切换状态
     *  cid 表单数据cid
     * */
    public JsonNode mocSwitchState(String cid)  {
        JsonNode result=null;//接口返回信息
        try{
            Record record = Db.findFirst("SELECT * FROM fn_form_data WHERE conflict_id= ?", cid);
            //通过row_id获取父级数据，得到登入权限
            Record parentRecord = Db.findFirst("select * from fn_form_data where conflict_id= ?",record.getStr("row_id"));
            String serviceUrl = parentRecord.getStr("ATTRIB_35");//接口标识符
            String serviceParam = parentRecord.getStr("ATTRIB_36");//登入信息json
            //调用登入接口获得登入认证token
            JsonNode jsonNode = mocExecPost(serviceUrl, serviceParam, null);
            String token = jsonNode.get("data").get("token").asText();
            String callMethod = record.getStr("ATTRIB_08");//调用方式
            String addressUrl = record.getStr("ATTRIB_04");//接口地址
            String params = record.getStr("ATTRIB_12");//参数信息
            JSONObject jsonParam = JSON.parseObject(params);
            boolean state = (boolean) jsonParam.get("state");
           if(state){
               jsonParam.put("state",false);
               //更新工作状态和参数信息
               Db.update("update fn_form_data set ATTRIB_07=? , ATTRIB_12=?  where conflict_id= ? ","停止",jsonParam.toString(),cid);
           }else {
               jsonParam.put("state",true);
               //更新工作状态和参数信息
               Db.update("update fn_form_data set ATTRIB_07=? , ATTRIB_12=? where conflict_id= ? ","启动",jsonParam.toString(),cid);
           }
            if("get".equals(callMethod.toLowerCase())){
                result = mocExecGet(addressUrl, token);
            }else {
                result  = mocExecPost(addressUrl, jsonParam.toString(), token);
            }
            return  result;
        }catch (Exception e){
            e.printStackTrace();
            ObjectMapper objectMapper = new ObjectMapper(); // 创建一个ObjectMapper对象，用于处理JSON
            ObjectNode res = objectMapper.createObjectNode(); // 创建一个ObjectNode对象
            // 添加msg字段到ObjectNode对象中
            res.put("msg", e.toString());
            return res;
        }
    }


    /**
     * 服务与配置变更管理 操作执行
     *  cid 表单数据cid
     * */
    public JsonNode mocExec(String cid){
        JsonNode result=null;//接口返回信息
        try{
            Record record = Db.findFirst("select * from fn_form_data where conflict_id= ?",cid);
            //通过row_id获取父级数据，得到登入权限
            Record parentRecord = Db.findFirst("select * from fn_form_data where conflict_id= ?",record.getStr("row_id"));
            String serviceUrl = parentRecord.getStr("ATTRIB_35");//接口标识符
            String serviceParam = parentRecord.getStr("ATTRIB_36");//登入信息json
            //调用登入接口获得登入认证token
            JsonNode jsonNode = mocExecPost(serviceUrl, serviceParam, null);
            String token = jsonNode.get("data").get("token").asText();
            String callMethod = record.getStr("ATTRIB_08");//调用方式
            String addressUrl = record.getStr("ATTRIB_04");//接口地址
            String params = record.getStr("ATTRIB_12");//参数信息
            if("get".equals(callMethod.toLowerCase())){
                 result = mocExecGet(addressUrl, token);
            }else {
                result  = mocExecPost(addressUrl, params, token);
            }
            return  result;
        }catch (Exception e){
            e.printStackTrace();
            ObjectMapper objectMapper = new ObjectMapper(); // 创建一个ObjectMapper对象，用于处理JSON
            ObjectNode res = objectMapper.createObjectNode(); // 创建一个ObjectNode对象
            // 添加msg字段到ObjectNode对象中
            res.put("msg", e.toString());
            return res;
        }
    }

    /**
     * 服务与配置变更管理 执行Post请求
     *  url 请求地址
     *  param 请求参数
     *  jwtoken 认证信息
     * */
    public JsonNode  mocExecPost(String url,String param,String jwtoken) throws Exception {
        // 创建Httpclient对象
            CloseableHttpClient httpClient = HttpClients.custom()
                    .setDefaultRequestConfig(RequestConfig.custom()
                            .setConnectTimeout(5000) //连接超时时间
                            .setSocketTimeout(5000) //读取超时时间
                            .setConnectionRequestTimeout(5000) //请求超时时间
                            .build())
                    .build();
            CloseableHttpResponse response = null;
            JsonNode jsonNode =null;
            try {
                // 创建Http Post请求
                HttpPost httpPost = new HttpPost(url);
                httpPost.setHeader("accept"," application/json");
                //认证不为空，则加上认证信息
                if(StringUtils.isNotBlank(jwtoken)){
                    httpPost.setHeader("jwtoken",jwtoken);
                }
                // 创建参数列表
                if (param != null) {
                    StringEntity postingString = new StringEntity(param, ContentType.APPLICATION_JSON);
                    httpPost.setEntity(postingString);
                }
                // 执行http请求
                response = httpClient.execute(httpPost);
                String resultString = EntityUtils.toString(response.getEntity(), "utf-8");
                // 将字符串转换为JSON对象
                ObjectMapper objectMapper = new ObjectMapper();
                jsonNode = objectMapper.readValue(resultString, JsonNode.class);
                response.close();
            } catch (Exception e) {
                throw e;
            }
            return jsonNode;
    }

    /**
     * 服务与配置变更管理 执行Get请求
     *  url 请求地址
     *  jwtoken 认证信息
     * */
    public JsonNode mocExecGet(String url,String jwtoken) throws Exception {
        // 创建Httpclient对象
        // 创建Httpclient对象
        CloseableHttpClient httpClient = HttpClients.custom()
                .setDefaultRequestConfig(RequestConfig.custom()
                        .setConnectTimeout(5000) //连接超时时间
                        .setSocketTimeout(5000) //读取超时时间
                        .setConnectionRequestTimeout(5000) //请求超时时间
                        .build())
                .build();
        CloseableHttpResponse response = null;
        JsonNode jsonNode =null;
        try {
            // 创建Http get请求
            HttpGet httpGet = new HttpGet(url);
            httpGet.setHeader("accept"," application/json");
            //认证不为空，则加上认证信息
            if(StringUtils.isNotBlank(jwtoken)){
                httpGet.setHeader("jwtoken",jwtoken);
            }
            // 执行http请求
            response = httpClient.execute(httpGet);
            String resultString = EntityUtils.toString(response.getEntity(), "utf-8");
            // 将字符串转换为JSON对象
            ObjectMapper objectMapper = new ObjectMapper();
            jsonNode = objectMapper.readValue(resultString, JsonNode.class);
            response.close();
        } catch (Exception e) {
           throw e;
        }
        return jsonNode;
    }
}
